﻿using System; 
using System.Reflection;
using Titan.ExpressionAnalyse.PropertyAccessor;

namespace Titan
{

    /// <summary>
    /// 反射缓存实体类属性(PropertyInfo)或者字段(FieldInfo)的信息。
    /// 各类Attribute既可以标注在属性上，又可以标注的字段上，通过这个类的包装可以更加方便地获取或者设置属性值。
    /// 可以参考本类中的构造函数，GetValue和SetValue方法的源码。
    /// </summary>
    public class PropertyAdapter
    {
        enum AdapterType
        {
            Property,
            Field,
            Dinamic
        }
        private AdapterType adapterType;
        private PropertyAccessor propertyAccessor { get; set; }
        private FieldAccessor fieldAccessor { get; set; }

        /// <summary>
        /// 通过传入一个属性(PropertyInfo)或者字段(FieldInfo)来构造
        /// </summary>
        /// <param name="memberInfo">属性或者字段</param>
        public PropertyAdapter(MemberInfo memberInfo)
        {
            if (memberInfo is PropertyInfo)
            {
                PropertyInfo propertyInfo = (PropertyInfo)memberInfo;
                this.propertyAccessor = new PropertyAccessor(propertyInfo);
                this.PropertyType = new EntityType(propertyInfo.PropertyType);
                this.adapterType = AdapterType.Property;
            }
            else
            {
                FieldInfo fieldInfo = (FieldInfo)memberInfo;
                this.fieldAccessor = new FieldAccessor(fieldInfo);
                this.PropertyType = new EntityType(fieldInfo.FieldType);
                this.adapterType = AdapterType.Field;
            }
            this.PropertyName = memberInfo.Name;
        }

        /// <summary>
        /// 针对DynamicEntity设置
        /// </summary>
        /// <param name="propertyName">属性名称</param>
        /// <param name="propertyType">属性类型</param>
        public PropertyAdapter(string propertyName, EntityType propertyType)
        {
            this.PropertyName = propertyName;
            this.PropertyType = propertyType;
            this.adapterType = AdapterType.Dinamic;
        }


        /// <summary>
        /// 获取属性或字段的Type
        /// </summary>
        public EntityType PropertyType { get; private set; }
        /// <summary>
        /// 获取属性或字段的属性名
        /// </summary>
        public string PropertyName { get; private set; }





        /// <summary>
        /// 获取属性或字段的值
        /// </summary>
        /// <param name="obj">对象</param>
        /// <returns></returns>
        public object GetValue(object obj)
        {
            switch (adapterType)
            {
                case AdapterType.Property:
                    return propertyAccessor.Get(obj);
                case AdapterType.Field:
                    return fieldAccessor.Get(obj);
                default:
                    //return ((IDynamicEntity)obj)[PropertyName];
                    return ((IDynamicEntity)obj).Get(PropertyName);
            }
        }

        /// <summary>
        /// 设置属性或字段的值
        /// </summary>
        /// <param name="obj">对象</param>
        /// <param name="value">属性或字段值</param>
        public void SetValue(object obj, object value)
        {
            switch (adapterType)
            {
                case AdapterType.Property:
                    propertyAccessor.Set(obj, value);
                    break;
                case AdapterType.Field:
                    fieldAccessor.Set(obj, value);
                    break;
                default:
                    //((IDynamicEntity)obj)[PropertyName] = value;
                    ((IDynamicEntity)obj).Set(PropertyName, value);
                    break;
            }
        }



    }


    ///// <summary>
    ///// 反射缓存实体类属性(PropertyInfo)或者字段(FieldInfo)的信息。
    ///// 各类Attribute既可以标注在属性上，又可以标注的字段上，通过这个类的包装可以更加方便地获取或者设置属性值。
    ///// 可以参考本类中的构造函数，GetValue和SetValue方法的源码。
    ///// </summary>
    //public class PropertyAdapter
    //{
    //    enum AdapterType
    //    {
    //        Property,
    //        Field,
    //        Dinamic
    //    }
    //    private AdapterType adapterType;
    //    private PropertyInfo propertyInfo { get; set; }
    //    private FieldInfo fieldInfo { get; set; } 

    //    /// <summary>
    //    /// 通过传入一个属性(PropertyInfo)或者字段(FieldInfo)来构造
    //    /// </summary>
    //    /// <param name="memberInfo">属性或者字段</param>
    //    public PropertyAdapter(MemberInfo memberInfo)
    //    {
    //        if (memberInfo is PropertyInfo)
    //        {
    //            this.propertyInfo = (PropertyInfo)memberInfo;
    //            this.PropertyType = new EntityType(propertyInfo.PropertyType);
    //            this.adapterType = AdapterType.Property;
    //        }
    //        else
    //        {
    //            this.fieldInfo = (FieldInfo)memberInfo;
    //            this.PropertyType = new EntityType(fieldInfo.FieldType);
    //            this.adapterType = AdapterType.Field;
    //        }
    //        this.PropertyName = memberInfo.Name;
    //    }

    //    /// <summary>
    //    /// 针对DynamicEntity设置
    //    /// </summary>
    //    /// <param name="propertyName">属性名称</param>
    //    /// <param name="propertyType">属性类型</param>
    //    public PropertyAdapter(string propertyName,EntityType propertyType)
    //    {
    //        this.PropertyName = propertyName;
    //        this.PropertyType = propertyType;
    //        this.adapterType = AdapterType.Dinamic;
    //    } 


    //    /// <summary>
    //    /// 获取属性或字段的Type
    //    /// </summary>
    //    public EntityType PropertyType { get; private set; } 
    //    /// <summary>
    //    /// 获取属性或字段的属性名
    //    /// </summary>
    //    public string PropertyName { get; private set; }





    //    /// <summary>
    //    /// 获取属性或字段的值
    //    /// </summary>
    //    /// <param name="obj">对象</param>
    //    /// <returns></returns>
    //    public object GetValue(object obj)
    //    {
    //        switch (adapterType)
    //        {
    //            case AdapterType.Property:
    //                return propertyInfo.GetValue(obj, null); 
    //            case AdapterType.Field:
    //                return fieldInfo.GetValue(obj); 
    //            default:
    //                return ((IDynamicEntity)obj)[PropertyName];
    //        } 
    //    }

    //    /// <summary>
    //    /// 设置属性或字段的值
    //    /// </summary>
    //    /// <param name="obj">对象</param>
    //    /// <param name="value">属性或字段值</param>
    //    public void SetValue(object obj, object value)
    //    {
    //        switch (adapterType)
    //        {
    //            case AdapterType.Property:
    //                propertyInfo.SetValue(obj, value, null);
    //                break;
    //            case AdapterType.Field:
    //                fieldInfo.SetValue(obj, value);
    //                break;
    //            default:
    //                ((IDynamicEntity)obj)[PropertyName]=value;
    //                break;
    //        } 
    //    }
        

         
    //}
}
